package util;

import core.context.InputContext;
import domain.Point;
import domain.Square;
import domain.SquareType;

public class Util {

	/**
	 * return the index of the left square of the current square, for example,
	 * the map is 5 * 6 and current square is [1][2],then its left is [1][1],
	 * however,if the square is [1][0],then it has no left,return -1
	 * 
	 * @param index
	 * @return
	 */
	public static int left(int index) {
		int mapWidth = InputContext.current.getWidth();
		if (index % mapWidth == 0)
			return -1;
		else
			return index - 1;
	}

	public static int right(int index) {
		int mapWidth = InputContext.current.getWidth();
		if (index % mapWidth == (mapWidth - 1))
			return -1;
		else
			return index + 1;
	}

	public static int up(int index) {
		int mapWidth = InputContext.current.getWidth();
		// the first row has no up
		if (index <= (mapWidth - 1))
			return -1;
		else
			return index - mapWidth;
	}

	/**
	 * transform the x and y coordinate of a square into an index, for
	 * example,if the map is 5(rows) * 6(columns),and the square is [2][3],the
	 * index is 2 * 6 + 3 = 15
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public static int transformCoordinateIntoIndex(int x, int y) {
		int mapWidth = InputContext.current.getWidth();
		return y * mapWidth + x;
	}

	public static boolean available(int index) {
		return !isDefendedSquare(index) && !isObstacleSquare(index);
	}

	public static int transferSquareToIndex(Square s) {
		return transformCoordinateIntoIndex(s.getPosition().getX(), s
				.getPosition().getY());
	}

	/**
	 * the inversion of transformCoordinateIntoIndex
	 * 
	 * @param index
	 * @return
	 */
	public static Point transformIndexToCoordinate(int index) {
		int mapWidth = InputContext.current.getWidth();
		int y = index / mapWidth;
		int x = index % mapWidth;
		return new Point(x, y);
	}

	public static int down(int index) {
		int mapWidth = InputContext.current.getWidth();
		int mapHeight = InputContext.current.getHeight();
		Point p = transformIndexToCoordinate(index);
		// the first row has no down
		if (p.getY() == mapHeight - 1) {
			return -1;
		} else
			return index + mapWidth;
	}

	public static boolean isObstacleSquare(int x, int y) {
		return isObstacleSquare(InputContext.current.getMap(), x, y);
	}

	public static boolean isDefendedSquare(int x, int y) {
		return isDefendedSquare(InputContext.current.getMap(), x, y);
	}

	public static boolean isDefendedSquare(int index) {
		return isDefendedSquare(InputContext.current.getMap(), index);
	}

	public static boolean contains(int[] values, int key) {
		for (int i = 0; i < values.length; i++) {
			if (values[i] - 1 == key)
				return true;
		}
		return false;
	}
	
	public static double distance(Point p1, Point p2) {
		return Math.sqrt((p1.getX() - p2.getX()) * (p1.getX() - p2.getX())
				+ (p1.getY() - p2.getY()) * (p1.getY() - p2.getY()));
	}

	/**
	 * tell whether we can go through this square, for example,we can go through
	 * empty square and defended square,but not other squares.
	 * 
	 * @param index
	 * @return
	 */
	public static boolean isObstacleSquare(int index) {
		return isObstacleSquare(InputContext.current.getMap(), index);
	}

	public static boolean isObstacleSquare(Square[][] map, int index) {
		Point p = transformIndexToCoordinate(index);
		return isObstacleSquare(map, p.getX(), p.getY());
	}

	public static boolean isObstacleSquare(Square[][] map, int x, int y) {
		SquareType type = map[y][x].getType();
		boolean ret = type.equals(SquareType.OBSTACLE)
				|| type.equals(SquareType.TOWER);
		return ret;
	}

	public static boolean isDefendedSquare(Square[][] map, int index) {
		Point p = transformIndexToCoordinate(index);
		return isDefendedSquare(map, p.getX(), p.getY());
	}

	public static boolean isDefendedSquare(Square[][] map, int x, int y) {
		SquareType type = map[y][x].getType();
		boolean ret = type.equals(SquareType.DEFENDED);
		return ret;
	}
	
	public static boolean isTower(Square[][] map, int x, int y) {
		SquareType type = map[y][x].getType();
		boolean ret = type.equals(SquareType.TOWER);
		return ret;
	}
	
	public static boolean isTower(Square[][] map, int index) {
		Point p = transformIndexToCoordinate(index);
		return isTower(map, p.getX(), p.getY());
	}
}
